//
//  BluetoothPeripheralManager.swift
//  Nexs
//
//  Created by roni on 2025/7/30.
//

import Foundation
import CoreBluetooth

/// 蓝牙外设管理器，用于将手机作为蓝牙外设向外广播数据
public class BluetoothPeripheralManager: NSObject {
    
    // MARK: - Properties
    /// 代理对象，用于接收广播和连接事件回调
    public weak var delegate: BluetoothPeripheralManagerDelegate?
    
    /// CoreBluetooth外设管理器
    private var peripheralManager: CBPeripheralManager?
    private let blueQueue: DispatchQueue = DispatchQueue(label: "com.nexs.bluetooth.peripheral")
    
    /// 广播定时器，用于控制广播时长
    private var broadcastTimer: Timer?
    
    /// 当前广播配置
    private var currentConfiguration: BroadcastConfiguration?
    
    /// 广播开始时间
    private var broadcastStartTime: Date?
    
    /// 已连接的中央设备集合
    private var connectedCentrals: Set<CBCentral> = []
    
    /// 已添加的服务列表
    private var addedServices: [CBMutableService] = []
    
    private var logger: BluetoothLogable? {
        return currentConfiguration?.logger
    }
    
    // MARK: - State Properties
    /// 当前广播状态
    public private(set) var broadcastState: PeripheralBroadcastState = .idle {
        didSet {
            if oldValue != broadcastState {
                DispatchQueue.main.async { [weak self] in
                    guard let self = self else { return }
                    self.delegate?.peripheralManager(self, didChangeState: self.broadcastState)
                }
            }
        }
    }
    
    /// 蓝牙是否可用
    public var isBluetoothAvailable: Bool {
        return peripheralManager?.state == .poweredOn
    }
    
    /// 是否正在广播
    public var isBroadcasting: Bool {
        return broadcastState == .broadcasting && (peripheralManager?.isAdvertising ?? false)
    }
    
    /// 当前连接的中央设备数量
    public var connectedCentralCount: Int {
        return connectedCentrals.count
    }
    
    /// 当前广播统计信息
    public var currentStatistics: BroadcastStatistics? {
        guard let startTime = broadcastStartTime else { return nil }
        let endTime = broadcastState == .broadcasting ? nil : Date()
        return BroadcastStatistics(
            startTime: startTime,
            endTime: endTime,
            connectionCount: connectedCentrals.count
        )
    }
    
    // MARK: - Initialization
    public override init() {
        super.init()
    }
    
    /// 设置外设管理器
    private func setupPeripheralManager() {
        let options: [String: Any] = [
            CBPeripheralManagerOptionShowPowerAlertKey: false // 当蓝牙关闭时，系统会自动显示一个警告弹窗，提示用户开启蓝牙, 这里不打开
        ]
        
        peripheralManager = CBPeripheralManager(delegate: self, queue: nil, options: options)
    }
    
    // MARK: - Public Methods
    
    public func start() {
        setupPeripheralManager()
    }
    
    /// 开始广播
    /// - Parameter configuration: 广播配置
    public func startBroadcasting(with configuration: BroadcastConfiguration) {
        guard let peripheralManager = peripheralManager else {
            configuration.logger.log("蓝牙不可用，centralManager不存在")
            DispatchQueue.main.async { [weak self] in
                guard let self = self else { return }
                self.delegate?.peripheralManager(self, didFailToBroadcast: .bluetoothNotAvailable)
            }
            return
        }
        
        // 检查蓝牙状态
        guard peripheralManager.state == .poweredOn else {
            let error: PeripheralError
            switch peripheralManager.state {
            case .unauthorized:
                error = .bluetoothNotAuthorized
            case .poweredOff:
                error = .bluetoothPoweredOff
            case .unsupported:
                error = .bluetoothNotAvailable
            default:
                error = .bluetoothPoweredOff
            }
            
            DispatchQueue.main.async { [weak self] in
                guard let self = self else { return }
                self.delegate?.peripheralManager(self, didFailToBroadcast: error)
            }
            return
        }
        
        // 检查当前状态
        guard broadcastState == .idle else {
            logger?.log("外设管理器忙碌中，当前状态: \(broadcastState)")
            return
        }
        
        // 验证广播数据
        let advertisementData = configuration.advertisementData
        guard validateAdvertisementData(advertisementData) else {
            DispatchQueue.main.async { [weak self] in
                guard let self = self else { return }
                self.delegate?.peripheralManager(self, didFailToBroadcast: .advertisementDataTooLarge)
            }
            return
        }
        
        // 设置状态和配置
        broadcastState = .starting
        currentConfiguration = configuration
        broadcastStartTime = Date()
        
        // 开始广播
        logger?.log("开始广播，advertisementData: \(advertisementData)")
        peripheralManager.startAdvertising(advertisementData)
        
        // 设置广播定时器
        setupBroadcastTimer(duration: configuration.duration)
    }
    
    /// 停止广播
    public func stopBroadcasting() {
        guard broadcastState == .broadcasting || broadcastState == .starting else {
            logger?.log("没有正在进行的广播需要停止")
            return
        }
        
        logger?.log("停止广播...")
        broadcastState = .stopping
        
        // 停止广播
        peripheralManager?.stopAdvertising()
        
        // 清理定时器
        cleanupBroadcastTimer()
        
        // 创建统计信息并通知代理
        if let startTime = broadcastStartTime {
            let statistics = BroadcastStatistics(
                startTime: startTime,
                endTime: Date(),
                connectionCount: connectedCentrals.count
            )
            
            DispatchQueue.main.async { [weak self] in
                guard let self = self else { return }
                self.delegate?.peripheralManager(self, didStopBroadcasting: statistics)
            }
        }
        
        // 重置状态
        resetBroadcastState()
    }
    
    /// 更新广播配置（会重新开始广播）
    /// - Parameter configuration: 新的广播配置
    public func updateBroadcastConfiguration(_ configuration: BroadcastConfiguration) {
        let wasBoradcasting = isBroadcasting
        
        if wasBoradcasting {
            stopBroadcasting()
        }
        
        // 短暂延迟后重新开始广播
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in
            self?.startBroadcasting(with: configuration)
        }
    }
    
    /// 添加蓝牙服务
    /// - Parameter service: 要添加的可变服务
    public func addService(_ service: CBMutableService) {
        guard let peripheralManager = peripheralManager else {
            logger?.log("蓝牙不可用，centralManager不存在")
            DispatchQueue.main.async { [weak self] in
                guard let self = self else { return }
                self.delegate?.peripheralManager(self, didFailToBroadcast: .bluetoothNotAvailable)
            }
            return
        }
        
        guard peripheralManager.state == .poweredOn else {
            logger?.log("蓝牙未准备就绪，无法添加服务")
            DispatchQueue.main.async { [weak self] in
                guard let self = self else { return }
                self.delegate?.peripheralManager(self, didFailToBroadcast: .bluetoothPoweredOff)
            }
            return
        }
        
        logger?.log("添加服务: \(service.uuid)")
        peripheralManager.add(service)
    }
    
    /// 移除指定服务
    /// - Parameter service: 要移除的服务
    public func removeService(_ service: CBMutableService) {
        guard let peripheralManager = peripheralManager else {
            return
        }
        logger?.log("移除服务: \(service.uuid)")
        peripheralManager.remove(service)
        addedServices.removeAll { $0.uuid == service.uuid }
    }
    
    /// 移除所有服务
    public func removeAllServices() {
        guard let peripheralManager = peripheralManager else {
            return
        }
        
        logger?.log("移除所有服务")
        peripheralManager.removeAllServices()
        addedServices.removeAll()
    }
    
    /// 向订阅的中央设备发送数据更新
    /// - Parameters:
    ///   - value: 要发送的数据
    ///   - characteristic: 目标特征
    ///   - centrals: 目标中央设备列表，nil表示所有订阅设备
    /// - Returns: 是否成功发送
    @discardableResult
    public func updateValue(_ value: Data, for characteristic: CBMutableCharacteristic, onSubscribedCentrals centrals: [CBCentral]?) -> Bool {
        guard let peripheralManager = peripheralManager else {
            return false
        }
        
        let success = peripheralManager.updateValue(value, for: characteristic, onSubscribedCentrals: centrals)
        
        if success {
            logger?.log("数据更新发送成功，数据大小: \(value.count) 字节")
        } else {
            logger?.log("数据更新发送失败，可能需要等待 peripheralManagerIsReadyToUpdateSubscribers 回调")
        }
        
        return success
    }
    
    /// 响应读取请求
    /// - Parameters:
    ///   - request: 读取请求
    ///   - result: 响应结果
    public func respondToRequest(_ request: CBATTRequest, withResult result: CBATTError.Code) {
        guard let peripheralManager = peripheralManager else {
            return
        }
        
        peripheralManager.respond(to: request, withResult: result)
    }
    
    /// 响应写入请求
    /// - Parameters:
    ///   - request: 写入请求
    ///   - result: 响应结果
    public func respondToWriteRequest(_ request: CBATTRequest, withResult result: CBATTError.Code) {
        guard let peripheralManager = peripheralManager else {
            return
        }
        
        peripheralManager.respond(to: request, withResult: result)
    }
}

// MARK: - Private Methods
extension BluetoothPeripheralManager {
    /// 设置广播定时器
    private func setupBroadcastTimer(duration: TimeInterval?) {
        guard let duration = duration, duration > 0 else {
            logger?.log("未设置广播时长，将持续广播")
            return
        }
        
        DispatchQueue.main.async {
            self.logger?.log("设置广播定时器，时长: \(duration) 秒")
            self.broadcastTimer = Timer.scheduledTimer(withTimeInterval: duration, repeats: false) { [weak self] _ in
                self?.logger?.log("广播定时器触发，停止广播")
                self?.stopBroadcasting()
            }
        }
    }
    
    /// 清理广播定时器
    private func cleanupBroadcastTimer() {
        broadcastTimer?.invalidate()
        broadcastTimer = nil
    }
    
    /// 重置广播状态
    private func resetBroadcastState() {
        broadcastState = .idle
        currentConfiguration = nil
        broadcastStartTime = nil
    }
    
    /// 验证广播数据大小
    private func validateAdvertisementData(_ data: [String: Any]) -> Bool {
        // iOS对广播数据有严格的大小限制
        // 传统广播包最大31字节，扩展广播包最大255字节(扩展广播包需要设备支持蓝牙 5.0+， 且手机作为外设不可用)
        
        var estimatedSize = 0
        
        if let serviceUUIDs = data[CBAdvertisementDataServiceUUIDsKey] as? [CBUUID] {
            for uuid in serviceUUIDs {
                // 16位UUID = 2字节，128位UUID = 16字节
                estimatedSize += uuid.data.count + 1 // +1 for type field
            }
        }
        
        if let localName = data[CBAdvertisementDataLocalNameKey] as? String {
            estimatedSize += localName.utf8.count + 2 // +2 for length and type
        }
        
        if let manufacturerData = data[CBAdvertisementDataManufacturerDataKey] as? Data {
            estimatedSize += manufacturerData.count + 2 // +2 for length and type
        }
        
        if data[CBAdvertisementDataTxPowerLevelKey] != nil {
            estimatedSize += 3 // 1 byte for power + 2 for length and type
        }
        
        // 基本协议开销
        estimatedSize += 6
        
        let isValid = estimatedSize <= 100 // 保守估计，留一些余量
        
        if !isValid {
            logger?.log("广播数据过大，估算大小: \(estimatedSize) 字节")
        }
        
        return isValid
    }
    
    /// 处理外设管理器状态变化
    private func handlePeripheralManagerState(_ state: CBManagerState) {
        let message: String
        
        switch state {
        case .unknown:
            message = "蓝牙管理器状态未知"
        case .resetting:
            message = "蓝牙管理器正在重置"
            // 重置时停止当前广播
            if broadcastState == .broadcasting {
                resetBroadcastState()
            }
        case .unsupported:
            message = "设备不支持蓝牙外设功能"
            DispatchQueue.main.async { [weak self] in
                guard let self = self else { return }
                self.delegate?.peripheralManager(self, didFailToBroadcast: .bluetoothNotAvailable)
            }
        case .unauthorized:
            message = "蓝牙权限未授权"
            DispatchQueue.main.async { [weak self] in
                guard let self = self else { return }
                self.delegate?.peripheralManager(self, didFailToBroadcast: .bluetoothNotAuthorized)
            }
        case .poweredOff:
            message = "蓝牙已关闭"
            // 蓝牙关闭时停止广播
            if broadcastState == .broadcasting {
                stopBroadcasting()
            }
        case .poweredOn:
            message = "蓝牙已开启，外设功能可用"
        @unknown default:
            message = "未知的蓝牙管理器状态: \(state.rawValue)"
        }
        
        logger?.log("外设管理器状态: \(message)")
        
        DispatchQueue.main.async { [weak self] in
            guard let self = self else { return }
            self.delegate?.peripheralManager(self, didChangeCentralManagerState: state, message: message)
        }
    }
}

// MARK: - CBPeripheralManagerDelegate
extension BluetoothPeripheralManager: CBPeripheralManagerDelegate {
    /// 外设管理器状态更新
    public func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
        logger?.log("外设管理器状态更新: \(peripheral.state.rawValue)")
        handlePeripheralManagerState(peripheral.state)
    }
    
    /// 开始广播回调
    public func peripheralManagerDidStartAdvertising(_ peripheral: CBPeripheralManager, error: Error?) {
        if let error = error {
            logger?.log("开始广播失败: \(error.localizedDescription)")
            broadcastState = .failed
            DispatchQueue.main.async { [weak self] in
                guard let self = self else { return }
                self.delegate?.peripheralManager(self, didFailToBroadcast: .startBroadcastFailed)
            }
        } else {
            logger?.log("广播已成功开始")
            broadcastState = .broadcasting
            
            if let config = currentConfiguration {
                DispatchQueue.main.async { [weak self] in
                    guard let self = self else { return }
                    self.delegate?.peripheralManager(self, didStartBroadcasting: config)
                }
            }
        }
    }
    
    /// 中央设备订阅特征
    public func peripheralManager(_ peripheral: CBPeripheralManager, central: CBCentral, didSubscribeTo characteristic: CBCharacteristic) {
        logger?.log("中央设备订阅特征: \(central.identifier) -> \(characteristic.uuid)")
        connectedCentrals.insert(central)
        
        DispatchQueue.main.async { [weak self] in
            guard let self = self else { return }
            self.delegate?.peripheralManager(self, didReceiveConnectionFrom: central)
        }
    }
    
    /// 中央设备取消订阅特征
    public func peripheralManager(_ peripheral: CBPeripheralManager, central: CBCentral, didUnsubscribeFrom characteristic: CBCharacteristic) {
        logger?.log("中央设备取消订阅特征: \(central.identifier) -> \(characteristic.uuid)")
        connectedCentrals.remove(central)
        
        DispatchQueue.main.async { [weak self] in
            guard let self = self else { return }
            self.delegate?.peripheralManager(self, didDisconnectFrom: central)
        }
    }
    
    /// 收到读取请求
    public func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveRead request: CBATTRequest) {
        logger?.log("收到读取请求 - 特征: \(request.characteristic.uuid), 中央设备: \(request.central.identifier)")
        
        DispatchQueue.main.async { [weak self] in
            guard let self = self else { return }
            self.delegate?.peripheralManager(self, didReceiveReadRequest: request)
        }
    }
    
    /// 收到写入请求
    public func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveWrite requests: [CBATTRequest]) {
        logger?.log("收到写入请求，数量: \(requests.count)")
        
        for request in requests {
            logger?.log("- 特征: \(request.characteristic.uuid), 数据大小: \(request.value?.count ?? 0) 字节")
        }
        
        DispatchQueue.main.async { [weak self] in
            guard let self = self else { return }
            self.delegate?.peripheralManager(self, didReceiveWriteRequests: requests)
        }
    }
    
    /// 准备更新订阅者
    public func peripheralManagerIsReady(toUpdateSubscribers peripheral: CBPeripheralManager) {
        logger?.log("外设管理器准备更新订阅者")
        
        // 这里可以发送待发送的数据
        DispatchQueue.main.async { [weak self] in
            guard let self = self else { return }
            // 由于我们不知道具体的特征，这里传递nil
            // 实际使用时应当传递具体的特征对象
            if let characteristic = self.addedServices.first?.characteristics?.first {
                self.delegate?.peripheralManagerIsReady(self, toUpdateSubscribers: characteristic)
            }
        }
    }
    
    /// 添加服务回调
    public func peripheralManager(_ peripheral: CBPeripheralManager, didAdd service: CBService, error: Error?) {
        if let error = error {
            logger?.log("添加服务失败: \(error.localizedDescription)")
            DispatchQueue.main.async { [weak self] in
                guard let self = self else { return }
                self.delegate?.peripheralManager(self, didFailToBroadcast: .serviceCreationFailed)
            }
        } else {
            logger?.log("服务添加成功: \(service.uuid)")
            // 将服务添加到已添加服务列表
            if let mutableService = service as? CBMutableService {
                addedServices.append(mutableService)
            }
        }
    }
} 
